/*
 * Copyright (c) 2002 Boris Pruessmann and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Common Public License v0.5
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors:
 *    Boris Pruessmann - Initial implementation.
 */
package net.sourceforge.perforce.ui.internal.model;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.Date;

import net.sourceforge.perforce.core.PerforceException;
import net.sourceforge.perforce.core.api.IOpenedResult;
import net.sourceforge.perforce.core.api.IPerforceServer;
import net.sourceforge.perforce.core.api.IWhereResult;
import net.sourceforge.perforce.core.resources.IChangelist;
import net.sourceforge.perforce.core.resources.LocalFile;
import net.sourceforge.perforce.ui.IPerforceUIConstants;
import net.sourceforge.perforce.ui.PerforceUIPlugin;
import net.sourceforge.perforce.ui.internal.Policy;
import net.sourceforge.perforce.ui.model.PerforceModelElement;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.model.IWorkbenchAdapter;

/**
  * @version $Revision: 45 $
  * @author  <a href="mailto:bpruessmann@users.sourceforge.net">Boris Pruessmann</a>
  *
  * TODO: Move IWorkbenchAdapter methods to own class.
  */
public class ChangelistElement extends PerforceModelElement 
                               implements IChangelist, IWorkbenchAdapter, IAdaptable
{
	// --------------------------------------------------------------------------- Private Variables
	
	/** Stores the Perforce Server. */
	private IPerforceServer server;
	/** Stores the id of the changelist. */
	private Integer id;
	/** Stores the changelist's description. */
	private String description;
	/** Stores the creation date. */
	private Date date;	
	/** Stores the associated client's name. */
	private String clientName;
	/** Stores the creating user's name. */
	private String userName;
	
	// ------------------------------------------------------------------------- Public Constructors
	
	/** Constructor for ChangelistElement. 
	  * 
	  * @param server reference to the Perforce server.
	  * @param id the changelist's id.
	  */
	public ChangelistElement(IPerforceServer server, Integer id)
	{
		this.server = server;
		this.id = id;
	}
	
	// ---------------------------------------------------------------- Public Methods (IChangelist)

	/** @see net.sourceforge.perforce.core.resources.IChangelist#getId() */
	public Integer getId() 
	{		
		return id;
	}

	/** @see net.sourceforge.perforce.core.resources.IChangelist#getClientName() */
	public String getClientName() 
	{
		return clientName;
	}
	
	/** @see net.sourceforge.perforce.core.resources.IChangelist#getUserName() */
	public String getUserName() 
	{
		return userName;
	}

	/** @see net.sourceforge.perforce.core.resources.IChangelist#getDate() */
	public Date getDate() 
	{
		return date;
	}

	/** @see net.sourceforge.perforce.core.resources.IChangelist#getDescription() */
	public String getDescription() 
	{
		return description;
	}

	/** @see net.sourceforge.perforce.core.resources.IChangelist#getStatus() */
	public String getStatus() 
	{
		return IChangelist.STATUS_PENDING;
	}
	
	
	/** Call this method to retrieve the server to which this changelist element belongs.
	  * 
	  * @return the perforce server.
	  */
	public IPerforceServer getServer()
	{
		return server;
	}

	// ---------------------------------------------------------- Public Methods (IWorkbenchAdapter)

	/** @see org.eclipse.ui.model.IWorkbenchAdapter#getChildren(Object) */
	public Object[] getChildren(Object o) 
	{
		if (!(o instanceof IChangelist))
		{
			return new Object[0];
		}
							
		LocalFile[] result = new LocalFile[0];
		try
		{
			IChangelist changelist = (IChangelist) o;
			IOpenedResult[] openedResults = server.opened(changelist);
			
			result = new LocalFile[openedResults.length];
			for (int i = 0; i < openedResults.length; i++)
			{
				IOpenedResult openedResult = openedResults[i];
				IWhereResult whereResult = server.where(openedResult.getDepotFilename());
				
				result[i] = LocalFile.create(server, new Path(whereResult.getLocalFilename()));
			}
		}
		catch (PerforceException e)
		{
			handle(e);
		}
		
		return result;
	}

	/** @see org.eclipse.ui.model.IWorkbenchAdapter#getImageDescriptor(Object) */
	public ImageDescriptor getImageDescriptor(Object o) 
	{
		if (!(o instanceof IChangelist))
		{
			return null;
		}
		
		String imageId = IPerforceUIConstants.IMG_CLIENT_CHANGELIST;
		return PerforceUIPlugin.getPlugin().getImageDescriptor(imageId);
	}

	/** @see org.eclipse.ui.model.IWorkbenchAdapter#getLabel(Object) */
	public String getLabel(Object o) 
	{
		if (!(o instanceof IChangelist))
		{
			return null;
		}
			
		IChangelist changelist = (IChangelist) o;

		String shortendDescription = cleanup(changelist.getDescription());
		if (shortendDescription.length() >= 40)
		{
			shortendDescription = shortendDescription.substring(0, 39) + "...";        //$NON-NLS-1$
		}
		
		return Policy.bind(
			"ChangelistElement.getLabel", changelist.getId(), shortendDescription);    //$NON-NLS-1$
	}

	/** @see org.eclipse.ui.model.IWorkbenchAdapter#getParent(Object) */
	public Object getParent(Object o) 
	{
		return null;
	}
	
	// ----------------------------------------------------------------- Public Methods (IAdaptable)
	
	/** @see org.eclipse.core.runtime.IAdaptable#getAdapter(Class) */
	public Object getAdapter(Class adapter) 
	{
		if (adapter == IWorkbenchAdapter.class)
		{
			return this;
		}
		
		return null;
	}
	
	// --------------------------------------------------------------------- Public Methods (Object)
	
	/** @see java.lang.Object#equals(java.lang.Object) */
	public boolean equals(Object object) 
	{
		if (this == object)
		{
			return true;
		}
			
		if (!(object instanceof IChangelist))
		{
			return false;
		}
		
		IChangelist other = (IChangelist) object;
		
		boolean flag = getServer().equals(other.getServer());
		flag &= getId().equals(other.getId());
		
		return flag;
	}
	
	/** @see java.lang.Object#hashCode() */
	public int hashCode() 
	{
		return getId().hashCode() * getServer().hashCode();
	}

	// ------------------------------------------------------------------------------------- Methods
	
	/** Call this method to set the date of the changelist. 
	  * 
	  * @param date the date.
	  */
	void setDate(Date date)
	{
		this.date = date;	
	}
	
	/** Call this method to set the description.
	  * 
	  * @param description the description.
	  */
	void setDescription(String description)
	{
		this.description = description;
	}
	
	/** Sets the client name.
	  * 
	  * @param clientName the name of the client.
	  */
	void setClientName(String clientName)
	{
		this.clientName = clientName;
	}
	
	/** Sets the user name.
	  *
	  * @param userName name of the user.
	  */
	void setUserName(String userName)
	{
		this.userName = userName;
	}

	// ----------------------------------------------------------------------------- Private Methods

	/** Returns a version of text with CR/LF converted to spaces.
	  * 
	  * @param text to convert.
	  * @return the converted text.
	  */
	private String cleanup(String text)
	{
		StringBuffer result = new StringBuffer();
		BufferedReader reader = new BufferedReader(new StringReader(text));

		try
		{
			String line = null;
			while ((line = reader.readLine()) != null)
			{
				result.append(line).append(' ');
			}
			
			return result.toString().trim();
		}
		catch (IOException e)
		{
			handle(e);
		}
		
		return text;
	}		
}
